package org.chz.system;

import org.springframework.stereotype.Component;
import org.chz.utils.Pair;
import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;

@Component
public class WebPageQuery {
    /* 偏移库 */
    private Map<Integer, Pair<Integer, Integer>> offsetLib;
    /* 倒排索引表 */
    private Map<String, Set<Pair<Integer, Double>>> invertIdxLib;


    public WebPageQuery() {
        this.offsetLib = new HashMap<>();
        this.invertIdxLib = new HashMap<>();
    }

    @PostConstruct
    private void initWebPageQuery() {
        readOffsetLib();
        readIvtIdxLib();
    }

    private void readOffsetLib() {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("newoffset.dat");
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {


            String line;
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split("\\s+");
                if (parts.length < 2) {
                    continue; // 跳过格式不正确的行
                }

                offsetLib.put(Integer.parseInt(parts[0]),
                        new Pair<>(Integer.parseInt(parts[1]), Integer.parseInt(parts[2])));

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void readIvtIdxLib() {
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("invertIndex.dat");
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {


            String line;
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split("\\s+");
                if (parts.length < 2) {
                    continue; // 跳过格式不正确的行
                }

                Set<Pair<Integer, Double>> set = new HashSet<>();
                for (int i = 1; i < parts.length; i += 2) {
                    set.add(new Pair<>(Integer.parseInt(parts[i]), Double.parseDouble(parts[i + 1])));
                }

                invertIdxLib.put(parts[0], set);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Map<Integer, Pair<Integer, Integer>> getOffsetLib() {
        return offsetLib;
    }

    public Map<String, Set<Pair<Integer, Double>>> getInvertIdxLib() {
        return invertIdxLib;
    }

    public void printOffLib() {
        offsetLib.forEach((o1, o2) -> System.out.println(o1.toString() + " " + o2.toString()));
    }

    public void printIvtIdxLib() {
        System.out.println(invertIdxLib.toString());
    }

    /* 求交集 */
    public Set<Integer> getIntersection(List<String> keys) {
        if (keys == null || keys.isEmpty()) {
            return Collections.emptySet();
        }

        Iterator<String> keyIterator = keys.iterator();
        String firstKey = keyIterator.next();
        Set<Pair<Integer, Double>> firstSet = invertIdxLib.get(firstKey);

        /* 这里使用TreeSet保证有序 */
        Set<Integer> intersection = new TreeSet<>();

        if (firstSet != null) {
            for (Pair<Integer, Double> pair : firstSet) {
                intersection.add(pair.getKey());
            }
        }

        while (keyIterator.hasNext()) {
            String key = keyIterator.next();
            Set<Pair<Integer, Double>> currentSet = invertIdxLib.get(key);

            if (currentSet == null) {
                intersection.clear();
                break;
            }

            Set<Integer> currentKeys = new HashSet<>();
            for (Pair<Integer, Double> pair : currentSet) {
                currentKeys.add(pair.getKey());
            }

            intersection.retainAll(currentKeys);

            if (intersection.isEmpty()) {
                break;
            }
        }

        return intersection;
    }


    public double[][] constructBaseVector(List<String> list) {
        Map<String, Integer> wordFrequencyMap = new HashMap<>();
        /* 计算句内词频 */
        list.forEach((String s) -> {
            if (wordFrequencyMap.containsKey(s)) {
                wordFrequencyMap.put(s, wordFrequencyMap.get(s) + 1);
            } else {
                wordFrequencyMap.put(s, 1);
            }
        });

        /* 计算特征向量 */
        double[][] baseVector = new double[list.size()][1];
        int i = 0;
        int N = offsetLib.size() + 1;
        for (String s : list) {
            int TF = wordFrequencyMap.get(s);

            int DF = 0;
            Set tmp = invertIdxLib.get(s);
            if (tmp != null) {
                DF = tmp.size() + 1;
            }

            baseVector[i++][0] = weight(TF, N, DF);
        }

        /* 基准向量要单位化 */
        double sum = 0;
        for (int row = 0; row < baseVector.length; row++) {
            sum += baseVector[row][0] * baseVector[row][0];
        }
        for (int row = 0; row < baseVector.length; row++) {
            baseVector[row][0] = baseVector[row][0] / Math.sqrt(sum);
        }

        return baseVector;
    }

    double weight(int TF, int N, int DF) {
        return TF * Math.log(N / (DF + 1));
    }


}


